// 版权归Go作者所有。版权所有。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

// Package lex为汇编程序实现词法分析。
package lex

import (
	"fmt"
	"log"
	"os"
	"strings"
	"text/scanner"

	"cmd/internal/src"
)

// 扫描令牌代表一个输入项。它是对符文的简单包装，如text/scanner返回的
// 。扫描仪，再加上几个额外的值。
type ScanToken rune

const (
	// Asm定义了一些双字符词素。我们为他们编了一个符文/扫描标记值——丑陋但简单。左移。
	RSH                                   // />>逻辑右移。
	ARR                                   // /->用于换档类型3的臂上，算术右移。
	ROT                                   // /@>用于换档类型4的臂上，向右旋转。
	Include                               // 包含的文件从这里开始
	BuildComment                          // 
	macroName                             // 不应展开的宏的名称
)

// IsRegisterShift报告令牌是否是ARM寄存器移位运算符之一。hu cdefg
func IsRegisterShift(r ScanToken) bool {
}

func (t ScanToken) String() string {
	switch t {
	case scanner.EOF:
		return "EOF"
	case scanner.Ident:
		return "identifier"
	case scanner.Int:
		return "integer constant"
	case scanner.Float:
		return "float constant"
	case scanner.Char:
		return "rune constant"
	case scanner.String:
		return "string constant"
	case scanner.RawString:
		return "raw string constant"
	case scanner.Comment:
		return "comment"
	default:
		return fmt.Sprintf("%q", rune(t))
	}
}

// NewLexer返回指定文件和给定链接上下文的lexer。
func NewLexer(name string) TokenReader {
	input := NewInput(name)
	fd, err := os.Open(name)
	if err != nil {
		log.Fatalf("%s\n", err)
	}
	input.Push(NewTokenizer(name, fd, fd))
	return input
}

// 此目录中的其他文件都包含TokenReader的实现。

// TokenReader与reader类似，但返回Token类型的lex Token。它还可以告诉您最近返回的令牌的文本是什么，以及在哪里找到的。
// 底层扫描器省略了除换行符以外的所有空格，因此输入看起来像一个
// 令牌流；原始间距丢失了，但我们不需要它。
type TokenReader interface {
	// Next返回下一个令牌。
	Next() ScanToken
	// 以下方法都引用了Next返回的最新令牌。
	// Text返回令牌的原始字符串表示形式。
	Text() string
	// File报告令牌的源文件名。
	File() string
	// Base报告令牌的位置基数。
	Base() *src.PosBase
	// SetBase设置位置基础。
	SetBase(*src.PosBase)
	// Line报告令牌的源行号。
	Line() int
	// Col报告令牌的源列号。
	Col() int
	// 关闭不需要任何拆卸。
	Close()
}

// 标记是扫描标记加上其字符串值。
// 一个宏被存储为一系列标记，并去掉空格。
type Token struct {
	ScanToken
	text string
}

// Make返回一个具有给定符文（ScanToken）和文本表示形式的令牌。
func Make(token ScanToken, text string) Token {
	// 如果符号以中心点开头，如在·x中，将其改写为“·x 
	if token == scanner.Ident && strings.HasPrefix(text, "\u00B7") {
		text = `""` + text
	}
	// 替换为。和/。
	text = strings.Replace(text, "\u00B7", ".", -1)
	text = strings.Replace(text, "\u2215", "/", -1)
	return Token{ScanToken: token, text: text}
}

func (l Token) String() string {
	return l.text
}

// 宏代表#定义的宏的定义。
type Macro struct {
	name   string   // 定义名称。
	args   []string // 形式参数。
	tokens []Token  // 宏体。
}

// Tokenize将字符串转换为标记列表；用于分析-D标志并在测试中使用。
func Tokenize(str string) []Token {
	t := NewTokenizer("command line", strings.NewReader(str), nil)
	var tokens []Token
	for {
		tok := t.Next()
		if tok == scanner.EOF {
			break
		}
		tokens = append(tokens, Make(tok, t.Text()))
	}
	return tokens
}
